package com.cloudfun.campusshare.controller;

import com.cloudfun.campusshare.common.constant.ApplicationStatus;
import com.cloudfun.campusshare.common.constant.ApplicationType;
import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.constant.RoleType;
import com.cloudfun.campusshare.common.exception.BusinessException;
import com.cloudfun.campusshare.common.model.dto.*;
import com.cloudfun.campusshare.common.model.vo.*;
import com.cloudfun.campusshare.common.response.BaseResult;
import com.cloudfun.campusshare.common.response.BaseResultFactory;
import com.cloudfun.campusshare.common.response.PageResult;
import com.cloudfun.campusshare.common.security.AuthRequired;
import com.cloudfun.campusshare.common.security.AuthenticationHolder;
import com.cloudfun.campusshare.entity.UserEntity;
import com.cloudfun.campusshare.repo.UserEntityRepo;
import com.cloudfun.campusshare.service.*;
import com.cloudfun.campusshare.util.ExcelUtils;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Set;

/**
 * @author linyangping
 * @date 2019/10/21
 */
@Validated
@Slf4j
@RestController
@RequestMapping("/v1/user")
@Api(value = "用户模块", description = "用户模块", position = 1)
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceOrderService deviceOrderService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private LoanService loanService;

    @Autowired
    private UserEntityRepo userEntityRepo;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private UserPreferWashPointService userPreferWashPointService;

    @ApiOperation(value = "商家、机构注册", notes = "商家、机构注册")
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    BaseResult<?> register(@ApiParam(value = "RegisterVo", required = true) @Valid @RequestBody RegisterVO registerVo) {
        return userService.register(registerVo);
    }

    @ApiOperation(value = "用户附加信息", notes = "用户附加信息")
    @RequestMapping(value = "/addition-info", method = RequestMethod.POST)
    BaseResult<?> additionInfo(@ApiParam(value = "UserAdditionInfoVO", required = true) @Valid @RequestBody UserAdditionInfoVO additionInfoVO) {
        return userService.additionInfo(additionInfoVO);
    }

    @ApiOperation(value = "获取用户信息", notes = "获取用户信息")
    @RequestMapping(method = RequestMethod.GET)
    @AuthRequired
    BaseResult<?> getUser() {
        return userService.getUser(AuthenticationHolder.getUserId());
    }

    @ApiOperation(value = "使用旧密码重置密码", notes = "使用旧密码重置密码")
    @RequestMapping(value = "/resetByOldPass", method = RequestMethod.POST)
    @AuthRequired
    BaseResult<?> resetPasswordByOldPassword(@ApiParam(value = "ResetPasswordByPassVO", required = true) @Valid @RequestBody ResetPasswordByPassVO resetPasswordByPassVO) {
        return userService.resetPasswordByOldPassword(resetPasswordByPassVO);
    }

    @ApiOperation(value = "使用验证码重置密码", notes = "使用验证码重置密码")
    @RequestMapping(value = "/resetByCode", method = RequestMethod.POST)
    BaseResult<?> resetPasswordByVerifyCode(@ApiParam(value = "ResetPasswordByCodeVO", required = true) @Valid @RequestBody ResetPasswordByCodeVO resetPasswordByCodeVO) {
        return userService.resetPasswordByVerifyCode(resetPasswordByCodeVO);
    }

    @ApiOperation(value = "修改用户信息", notes = "修改用户信息")
    @RequestMapping(value = "/modify", method = RequestMethod.PUT)
    @AuthRequired
    BaseResult<?> modify(@ApiParam(value = "UserInfoModifyVO", required = true) @Valid @RequestBody UserInfoModifyVO userInfoModifyVO) {
        return userService.modify(userInfoModifyVO);
    }

    @ApiOperation(value = "用户角色", notes = "获取用户角色")
    @RequestMapping(value = "/role", method = RequestMethod.GET)
    @AuthRequired
    BaseResult<Set<String>> getRole() {
        return BaseResultFactory.produceResult(Code.SUCCESS, AuthenticationHolder.getUserAuth().getRoleTypes());
    }

    @GetMapping("/count")
    @ApiOperation("商家数统计")
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<Long> countAll() {
        return userService.countAll();
    }

    @GetMapping("/overview/om")
    @ApiOperation("运营型商家数据概览")
    @AuthRequired(role = {RoleType.OPERATIONAL_MERCHANT, RoleType.ADMIN})
    BaseResult<OMDataOverviewVO> operationalMerchantDataOverview(@ApiParam(value = "用户id，管理员操作的话需要传")
                                                                 @RequestParam(required = false) String userId) {
        if (AuthenticationHolder.isAdmin() && StringUtils.isBlank(userId)) {
            throw new BusinessException(Code.PARAMETER_ERROR);
        }
        OMDataOverviewVO omDataOverviewVO = new OMDataOverviewVO();
        String orderTotal = deviceOrderService.orderTotal(userId);
        omDataOverviewVO.setOrderTotal(orderTotal);
        Long countInteractedDevices = deviceService.countInteractedDevices(userId);
        omDataOverviewVO.setInteractedDeviceNum(countInteractedDevices);
        Long countTodayInteractedDevices = deviceService.countTodayInteractedDevices(userId);
        omDataOverviewVO.setTodayInteractedDeviceNum(countTodayInteractedDevices);
        if (AuthenticationHolder.isAdmin()) {
            // 管理员暂时不需要这个数据
            Long schoolNumber = projectService.countSchoolByUserId(userId);
            omDataOverviewVO.setCooperativeSchoolNum(schoolNumber);
        }
        return BaseResultFactory.produceResult(Code.SUCCESS, omDataOverviewVO);
    }

    @GetMapping("/overview/pm")
    @ApiOperation("平台型商家数据概览")
    @AuthRequired(role = {RoleType.PLATFORM_MERCHANT, RoleType.ADMIN})
    BaseResult<PMDataOverviewVO> platformMerchantDataOverview(@ApiParam(value = "用户id，管理员操作的话需要传")
                                                              @RequestParam(required = false) String userId) {
        PMDataOverviewVO pmDataOverviewVO = new PMDataOverviewVO();
        Long countInteractedDevices = deviceService.countInteractedDevices(userId);
        pmDataOverviewVO.setInteractedDeviceNum(countInteractedDevices);
        Long countTodayInteractedDevices = deviceService.countTodayInteractedDevices(userId);
        pmDataOverviewVO.setTodayInteractedDeviceNum(countTodayInteractedDevices);
        return BaseResultFactory.produceResult(Code.SUCCESS, pmDataOverviewVO);
    }

    @GetMapping("/overview/fi")
    @ApiOperation("金融机构数据概览")
    @AuthRequired(role = {RoleType.FINANCIAL_INSTITUTIONS, RoleType.ADMIN})
    BaseResult<FIDataOverviewVO> financialInstitutionsDataOverview(@ApiParam(value = "用户id，管理员操作的话需要传")
                                                                   @RequestParam(required = false) String userId) {
        FIDataOverviewVO fiDataOverviewVO = new FIDataOverviewVO();
        String issuedLoanAmount = loanService.issuedLoanAmount(userId);
        fiDataOverviewVO.setIssuedLoanAmount(issuedLoanAmount);
        if (!AuthenticationHolder.isAdmin()) {
            Long countBorrower = loanService.countBorrower();
            fiDataOverviewVO.setBorrowerNum(countBorrower);
        }
        Long countNeedAudit = loanService.countNeedAudit(userId);
        fiDataOverviewVO.setNeedAuditLoanCount(countNeedAudit);
        if (!AuthenticationHolder.isAdmin()) {
            Long countAudited = loanService.countAudited();
            fiDataOverviewVO.setAuditedLoanCount(countAudited);
        }
        return BaseResultFactory.produceResult(Code.SUCCESS, fiDataOverviewVO);
    }

    @GetMapping("/overview/admin")
    @ApiOperation("平台运维数据概览")
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<AdminDataOverviewVO> adminDataOverview() {
        String currMonthOrderTotal = deviceOrderService.currMonthOrderTotal();
        Long fiCount = userService.countAuthenticatedUserByRoleType(RoleType.FINANCIAL_INSTITUTIONS);
        Long omCount = userService.countAuthenticatedUserByRoleType(RoleType.OPERATIONAL_MERCHANT);
        Long pmCount = userService.countAuthenticatedUserByRoleType(RoleType.PLATFORM_MERCHANT);
        Long interactedDevices = deviceService.countInteractedDevices();
        Long unprocessedApplicationCount = applicationService.countByTypeNotInAndStatusAndEnabled(Lists.newArrayList(ApplicationType.LOAN, ApplicationType.ISSUE_LOAN), ApplicationStatus.UNPROCESSED);
        AdminDataOverviewVO admin = new AdminDataOverviewVO();
        admin.setCurrMonthOrderTotalAmount(currMonthOrderTotal);
        admin.setAuthenticatedFiCount(fiCount);
        admin.setAuthenticatedOmCount(omCount);
        admin.setAuthenticatedPmCount(pmCount);
        admin.setInteractedDeviceCount(interactedDevices);
        admin.setNeedAuditApplicationCount(unprocessedApplicationCount);
        return BaseResultFactory.produceResult(Code.SUCCESS, admin);
    }

    @GetMapping("/overview/borrower")
    @ApiOperation("金融机构查看运营型商家概览信息")
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    BaseResult<BorrowerDataOverviewVO> borrowerDataOverview(@RequestParam String borrowerId) {
        String orderTotal = deviceOrderService.orderTotal(borrowerId);
        Long countInteractedDevices = deviceService.countBorrowerInteractedDevices(borrowerId);
        Long countTodayInteractedDevices = deviceService.countBorrowerTodayInteractedDevices(borrowerId);
        BorrowerDataOverviewVO borrowerDataOverviewVO = new BorrowerDataOverviewVO();
        borrowerDataOverviewVO.setOrderTotal(orderTotal);
        borrowerDataOverviewVO.setInteractedDeviceNum(countInteractedDevices);
        borrowerDataOverviewVO.setTodayInteractedDeviceNum(countTodayInteractedDevices);
        return BaseResultFactory.produceResult(Code.SUCCESS, borrowerDataOverviewVO);
    }

    @GetMapping("/list/simple-user")
    @ApiOperation("查询用户下拉列表")
    @AuthRequired
    BaseResult<List<UserSimpleVO>> authenticatedSimpleUser(@ApiParam(value = "RoleType", required = true) @RequestParam RoleType roleType) {
        List<UserSimpleVO> userSimpleVOList = userService.getAuthenticatedSimpleUserByRoleType(roleType);
        return BaseResultFactory.produceResult(Code.SUCCESS, userSimpleVOList);
    }

    @GetMapping("/borrower-detail")
    @ApiOperation("金融机构查询运营商家详情")
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    BaseResult<BorrowerDetailVO> borrowerDetail(@ApiParam(value = "运营商家id", required = true) @RequestParam String borrowerId) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.borrowerDetail(borrowerId));
    }

    @GetMapping("/borrower/list")
    @ApiOperation("金融机构查询运营商家列表")
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    BaseResult<PageResult<BorrowerListVO>> borrowerList(Pageable pageable, @ApiParam(value = "搜索关键字") @RequestParam(required = false) String value) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.searchBorrower(value, pageable));
    }

    @GetMapping("/borrower/history/list")
    @ApiOperation("金融机构查询历史运营商家列表")
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    public BaseResult borrowerHistoryList(Pageable pageable, @ApiParam(value = "关键字") @RequestParam(required = false) String keyword) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.getHistoryBorrowerList(pageable, keyword));
    }

    @GetMapping("/borrower/history/detail/{borrowId}")
    @ApiOperation("金融机构查询历史运营商家详情")
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    public BaseResult borrowerHistoryDetail(@ApiParam(value = "运营商家id", required = true) @PathVariable String borrowId) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.getBorrowHistoryDetail(borrowId));
    }

    @GetMapping("/borrower/history/list/export")
    @ApiOperation("金融机构导出历史运营商家列表")
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    public BaseResult borrowerHistoryListExport(@ApiParam(value = "关键字") @RequestParam(required = false) String keyword, HttpServletResponse response) throws IOException {
        List<BorrowHistoryExportVO> borrowerHistoryExportList = userService.getBorrowerHistoryExportList(keyword);
        String enterpriseName = userEntityRepo.findById(AuthenticationHolder.getUserId()).get().getEnterpriseName();
        ExcelUtils.exportExcel(borrowerHistoryExportList, null, "历史关联企业信息", BorrowHistoryExportVO.class, enterpriseName + "-HistoricalAffiliatedEnterprise", response);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @ApiOperation(value = "金融机构导出运营商家列表")
    @RequestMapping(value = "/borrower/export", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.FINANCIAL_INSTITUTIONS)
    void borrowerListExport(HttpServletResponse response, @ApiParam(value = "搜索关键字") @RequestParam(required = false) String value) throws IOException {
        long start = System.currentTimeMillis();
        List<BorrowerExportVO> exportVOList = userService.exportBorrower(value);
        log.debug("金融机构导出{}个运营商家信息记录耗时：{}ms", exportVOList.size(), (System.currentTimeMillis() - start));
        UserEntity userEntity = userEntityRepo.findById(AuthenticationHolder.getUserId()).orElse(null);
        ExcelUtils.exportExcel(exportVOList, null, "关联企业信息", BorrowerExportVO.class, userEntity.getEnterpriseName() + "-AffiliatedEnterprise", response);
    }

    @GetMapping("/om-detail")
    @ApiOperation("管理员查询运营商家详情")
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<MerchantFIDetailVO> omDetail(@ApiParam(value = "运营商id", required = true) @RequestParam String borrowerId) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.omDetail(borrowerId));
    }

    @GetMapping("/om/list")
    @ApiOperation("管理员查询运营商家列表")
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<PageResult<OMListVO>> omList(Pageable pageable, @ApiParam(value = "搜索关键字") @RequestParam(required = false) String value) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.searchOMs(value, pageable));
    }

    @ApiOperation(value = "管理员导出运营商家列表")
    @RequestMapping(value = "/om/export", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<?> omListExport(HttpServletResponse response, @ApiParam(value = "BatchOperateDTO", required = true) BatchOperateDTO<String> batchOperateDTO) throws IOException {
        if (CollectionUtils.isEmpty(batchOperateDTO.getIds()) && StringUtils.isBlank(batchOperateDTO.getSearchData()) && !BooleanUtils.isTrue(batchOperateDTO.getAll())) {
            return BaseResultFactory.produceResult(Code.PARAMETER_ERROR, "参数错误");
        }
        long start = System.currentTimeMillis();
        List<OMExportVO> exportVOList;
        if (!CollectionUtils.isEmpty(batchOperateDTO.getIds())) {
            exportVOList = userService.exportOM(batchOperateDTO.getIds(), null);
        } else if (null != batchOperateDTO.getSearchData()) {
            exportVOList = userService.exportOM(null, batchOperateDTO.getSearchData());
        } else {
            exportVOList = userService.exportOM(null, null);
        }
        log.debug("管理员导出{}个运营商家信息记录耗时：{}ms", exportVOList.size(), (System.currentTimeMillis() - start));
        ExcelUtils.exportExcel(exportVOList, null, "商家信息", OMExportVO.class, "ListOfMerchantEnterprises", response);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @ApiOperation(value = "管理员查询平台型商家列表")
    @GetMapping("/plat/list")
    @AuthRequired(role = RoleType.ADMIN)
    public BaseResult getPlatList(Pageable pageable, @ApiParam(value = "关键字") @RequestParam(required = false) String keyword) {
        PageResult<PlatEnterpriseListVO> platEnterpriseList = userService.getPlatEnterpriseList(pageable, keyword);
        return BaseResultFactory.produceResult(Code.SUCCESS, platEnterpriseList);
    }

    @ApiOperation(value = "管理员导出平台型商家列表")
    @RequestMapping(value = "/plat/export", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<?> pmListExport(HttpServletResponse response, @ApiParam(value = "BatchOperateDTO", required = true) BatchOperateDTO<String> batchOperateDTO) throws IOException {
        if (CollectionUtils.isEmpty(batchOperateDTO.getIds()) && StringUtils.isBlank(batchOperateDTO.getSearchData()) && !BooleanUtils.isTrue(batchOperateDTO.getAll())) {
            return BaseResultFactory.produceResult(Code.PARAMETER_ERROR, "参数错误");
        }
        long start = System.currentTimeMillis();
        List<PMExportVO> exportVOList;
        if (!CollectionUtils.isEmpty(batchOperateDTO.getIds())) {
            exportVOList = userService.exportPM(batchOperateDTO.getIds(), null);
        } else if (null != batchOperateDTO.getSearchData()) {
            exportVOList = userService.exportPM(null, batchOperateDTO.getSearchData());
        } else {
            exportVOList = userService.exportPM(null, null);
        }
        log.debug("管理员导出{}个平台型商家信息记录耗时：{}ms", exportVOList.size(), (System.currentTimeMillis() - start));
        ExcelUtils.exportExcel(exportVOList, null, "商家信息", PMExportVO.class, "ListOfMerchantEnterprises", response);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @ApiOperation(value = "查询平台型商家详情")
    @GetMapping("/plat/detail")
    @AuthRequired(role = RoleType.ADMIN)
    public BaseResult getPlateDetail(@ApiParam(value = "运营商id", required = true) @RequestParam String borrowerId) {
        MerchantFIDetailVO enterpriseDetail = userService.getPlatDetail(borrowerId);
        return BaseResultFactory.produceResult(Code.SUCCESS, enterpriseDetail);
    }

    @ApiOperation(value = "管理员查询金融机构列表")
    @GetMapping("/fi/list")
    @AuthRequired(role = RoleType.ADMIN)
    public BaseResult<PageResult<FIListVO>> getFiList(Pageable pageable, @ApiParam(value = "关键字") @RequestParam(required = false) String keyword) {
        PageResult<FIListVO> fiList = userService.searchFIs(keyword, pageable);
        return BaseResultFactory.produceResult(Code.SUCCESS, fiList);
    }

    @ApiOperation(value = "管理员导出金融机构列表")
    @RequestMapping(value = "/fi/export", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<?> fiListExport(HttpServletResponse response, @ApiParam(value = "BatchOperateDTO", required = true) BatchOperateDTO<String> batchOperateDTO) throws IOException {
        if (CollectionUtils.isEmpty(batchOperateDTO.getIds()) && StringUtils.isBlank(batchOperateDTO.getSearchData()) && !BooleanUtils.isTrue(batchOperateDTO.getAll())) {
            return BaseResultFactory.produceResult(Code.PARAMETER_ERROR, "参数错误");
        }
        long start = System.currentTimeMillis();
        List<FIExportVO> exportVOList;
        if (!CollectionUtils.isEmpty(batchOperateDTO.getIds())) {
            exportVOList = userService.exportFI(batchOperateDTO.getIds(), null);
        } else if (null != batchOperateDTO.getSearchData()) {
            exportVOList = userService.exportFI(null, batchOperateDTO.getSearchData());
        } else {
            exportVOList = userService.exportFI(null, null);
        }
        log.debug("管理员导出{}个金融机构信息记录耗时：{}ms", exportVOList.size(), (System.currentTimeMillis() - start));
        ExcelUtils.exportExcel(exportVOList, null, "商家信息", FIExportVO.class, "ListOfFinancialInstitutions", response);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @ApiOperation(value = "管理员查询金融机构详情")
    @GetMapping("/fi/detail")
    @AuthRequired(role = RoleType.ADMIN)
    public BaseResult<MerchantFIDetailVO> fiDetail(@ApiParam(value = "运营商id", required = true) @RequestParam String id) {
        MerchantFIDetailVO detail = userService.fiDetail(id);
        return BaseResultFactory.produceResult(Code.SUCCESS, detail);
    }

    @ApiOperation(value = "激活账号")
    @PostMapping("/activate")
    @AuthRequired
    public BaseResult<?> activateAccount(@ApiParam(value = "accountActivateDTO", required = true) @RequestBody AccountActivateDTO accountActivateDTO) {
        userService.activate(accountActivateDTO);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @ApiOperation(value = "客户列表")
    @RequestMapping(value = "/customer/list", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<?> customerList(Pageable pageable, @ApiParam(value = "搜索关键字") @RequestParam(required = false) String value) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.searchCustomer(value, pageable));
    }

    @ApiOperation(value = "客户统计")
    @RequestMapping(value = "/customer/count", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<?> customerCount() {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.customerCount());
    }

    @ApiOperation(value = "导出客户列表")
    @RequestMapping(value = "/customer/export", method = RequestMethod.GET)
    @AuthRequired(role = RoleType.ADMIN)
    BaseResult<?> customerListExport(HttpServletResponse response, @ApiParam(value = "BatchOperateDTO", required = true) BatchOperateDTO<String> batchOperateDTO) throws IOException {
        if (CollectionUtils.isEmpty(batchOperateDTO.getIds()) && StringUtils.isBlank(batchOperateDTO.getSearchData()) && !BooleanUtils.isTrue(batchOperateDTO.getAll())) {
            return BaseResultFactory.produceResult(Code.PARAMETER_ERROR, "参数错误");
        }
        long start = System.currentTimeMillis();
        List<CustomerExportVO> exportVOList;
        if (!CollectionUtils.isEmpty(batchOperateDTO.getIds())) {
            exportVOList = userService.exportCustomer(batchOperateDTO.getIds(), null);
        } else if (null != batchOperateDTO.getSearchData()) {
            exportVOList = userService.exportCustomer(null, batchOperateDTO.getSearchData());
        } else {
            exportVOList = userService.exportCustomer(null, null);
        }
        log.debug("管理员导出{}个客户信息记录耗时：{}ms", exportVOList.size(), (System.currentTimeMillis() - start));
        ExcelUtils.exportExcel(exportVOList, null, "客户信息", CustomerExportVO.class, "ListOfCustomer", response);
        return BaseResultFactory.produceEmptyResult(Code.SUCCESS);
    }

    @GetMapping("/search")
    @ApiOperation("账号列表")
    @AuthRequired
    public BaseResult<PageResult<AccountListVO>> searchAccount(Pageable pageable, AccountSearchDTO accountSearchDTO) {
        return BaseResultFactory.produceResult(Code.SUCCESS, userService.searchAccount(pageable, accountSearchDTO));
    }

    @ApiOperation(value = "新增", notes = "新增")
    @PostMapping
    @AuthRequired
    public BaseResult<?> create(@ApiParam(value = "createDTO", required = true) @Validated({AccountCreateDTO.Create.class})
                                @RequestBody AccountCreateDTO createDTO) {
        return userService.createAccount(createDTO);
    }

    @PutMapping
    @ApiOperation(value = "编辑", notes = "编辑")
    @AuthRequired
    BaseResult<?> modify(@ApiParam(value = "modifyDTO", required = true) @Valid @RequestBody AccountModifyDTO modifyDTO) {
        return userService.modifyAccount(modifyDTO);
    }

    @DeleteMapping
    @ApiOperation(value = "删除", notes = "删除")
    @AuthRequired
    BaseResult<?> delete(@ApiParam(value = "id", required = true) @RequestParam String id) {
        return userService.delete(id);
    }

    @ApiOperation(value = "详情", notes = "详情")
    @GetMapping("/detail")
    @AuthRequired
    BaseResult<UserDetailVO> detail(@ApiParam(value = "id", required = true) @RequestParam String id) {
        UserDetailVO detail = userService.detail(id);
        return BaseResultFactory.produceResult(Code.SUCCESS, detail);
    }

    @PutMapping("/enable")
    @ApiOperation(value = "启用\\禁用", notes = "启用\\禁用")
    @AuthRequired
    BaseResult<?> delete(@ApiParam(value = "id", required = true) @RequestParam String id,
                         @ApiParam(value = "enable", required = true) @RequestParam Boolean enable) {
        return userService.enable(id, enable);
    }

    @ApiOperation(value = "账户简单列表", notes = "账户简单列表")
    @GetMapping("/simpleList")
    public BaseResult<List<UserSimpleVO>> simpleList() {
        List<UserSimpleVO> userSimpleVOList = userService.getSimpleList();
        return BaseResultFactory.produceResult(Code.SUCCESS, userSimpleVOList);
    }

    @ApiOperation(value = "设置常用洗衣点", notes = "设置常用洗衣点")
    @PutMapping("/preferWashPoint")
    public BaseResult<String> setPreferWashPoint(@ApiParam(value = "洗衣点id") @RequestParam String washPointId) {
        UserPreferWashPointDTO userPreferWashPointDTO = new UserPreferWashPointDTO(AuthenticationHolder.getUserId(), washPointId);
        userPreferWashPointService.save(userPreferWashPointDTO);
        return BaseResultFactory.produceResult(Code.SUCCESS, "成功");
    }

    @ApiOperation(value = "获取常用洗衣点", notes = "获取常用洗衣点")
    @GetMapping("/preferWashPoint")
    public BaseResult<WashPointForQueryListVO> getPreferWashPoint() {
        WashPointForQueryListVO washPointForQueryListVO = userPreferWashPointService.getPreferWashPoint(AuthenticationHolder.getUserId());
        return BaseResultFactory.produceResult(Code.SUCCESS, washPointForQueryListVO);
    }

    @ApiOperation(value = "经销商添加子商户", notes = "经销商添加子商户")
    @PostMapping("/subClient/add")
    @AuthRequired(role = RoleType.AGENT)
    public BaseResult addSubClient(@RequestBody SubClientAddVO subClientAddVO){
        userService.addSubClient(subClientAddVO);
        return BaseResultFactory.produceSuccess();
    }


    @ApiOperation(value = "经销商查看客户列表", notes = "经销商查看客户列表")
    @GetMapping("/subClient/list")
    @AuthRequired(role = RoleType.AGENT)
    public BaseResult querySubClientList(Pageable pageable, @ApiParam(value = "搜索关键字",required = false) @RequestParam(required = false) String keyword){
        return BaseResultFactory.produceSuccess(userService.getSubClientList(pageable, keyword));
    }
}
